package ie.lawlor.amvc.swing;

import ie.lawlor.amvc.IDialogEnabledView;
import ie.lawlor.amvc.IView;
import ie.lawlor.amvc.ViewProxy;
import ie.lawlor.amvc.event.Event;

import java.awt.Component;
import java.awt.Container;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Toolkit;

import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JPopupMenu;
import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;

/**
 * Concrete implementation of ViewProxy that implements the remaining 
 * methods on the View interface.
 * @author blawlor
 */
public class SwingViewProxy extends ViewProxy {
  
  private SwingView view;
  protected SwingView parentView;
  protected String parentViewName;
  /**
   * @param view
   */
  public SwingViewProxy(String name, SwingView view) {
    super(name, view);
    this.view = view;
  }
  
  public SwingViewProxy(SwingView view) {
    super(view);
    this.view = view;
  }
  
  /**
   * Parents views may have many containers into which a child view component can 
   * be inserted. This method allows a by-name access to these parent containers.
   * @see ie.lawlor.amvc.View#addChild(ie.lawlor.amvc.View, java.lang.String)
   */
  public void addChild(IView childView, String viewName) {
    childView.setParent(view, viewName);
    if (childView instanceof JMenu){
      if (view instanceof JFrame) {
        ((JFrame)view).getJMenuBar().add((JMenu)childView);
      } else {
        throw new IllegalArgumentException("Cannot add a JMenu view to anything other than a JFrame");
      }
    } else if (childView instanceof JPopupMenu){
      // Nothing to add to anything!
    } else {
      Container parentContainer = view.getContainer(viewName);
      if (parentContainer != null){
        parentContainer.add((JComponent)childView);
      } else{
        throw new IllegalArgumentException("No such parent view: " + viewName);
      }
    }
  }
  
  /* (non-Javadoc)
   * @see com.informatica.amvc.View#addChild(com.informatica.amvc.View)
   */
  public void addChild(IView childView) {
    addChild(childView, null);
  }
  
  protected void initComponentEvents() {
    JComponent component = (JComponent)view;
//    component.addAncestorListener(new ViewAncestorListener(view));
  }
  
  public void addDialogChild(IDialogEnabledView childView) {
    childView.setUsingDialog(true);
    childView.setParent(view);
  }
  
  /* (non-Javadoc)
   * @see com.informatica.amvc.DialogEnabledView#setParent(com.informatica.amvc.View)
   */
  public void setParent(IView parentView) {
    setParent(parentView, null);
  }
  
  public void setParent(IView parentView, String parentViewName) {
    this.parentView = (SwingView)parentView;
    this.parentViewName = parentViewName;
    initComponentEvents();
  }
  
  public IView getParentView(){
    return parentView;
  }
  
  public void doCursorWaiting(Event e){
    view.setCursor(new Cursor(Cursor.WAIT_CURSOR));
  }
  
  public void doCursorNormal(Event e){
    view.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
  }
  
  
  private class ViewAncestorListener implements AncestorListener{
    IView view;
    public ViewAncestorListener(IView view){
      this.view = view;
    }
    public void ancestorAdded(AncestorEvent e) {
      view.setViewVisible(true);
    }
    public void ancestorMoved(AncestorEvent e) {
    }
    public void ancestorRemoved(AncestorEvent e) {
      view.setViewVisible(false);
    }
  }
  
  
  public void doHideView(Event e){
    logger.debug("Entering");
    if (isVisible()){
      parentView.getContainer(parentViewName).remove((Component)view);
    }
  }	
  
  //TODO Change this mechanism to take account of what kind of container the view is in. 
  public void doShowView(Event e){
    logger.debug("Entering");
    if (!isVisible()){
      Container container = parentView.getContainer(parentViewName);
      container.removeAll();
      logger.debug("About to add the view to its parent");
      container.add((Component)view);
      ((JComponent)container).updateUI();
    }
    logger.debug("Exiting");
  }
  
  
  
  public void doInitView(Event e) {
    logger.debug("Entering");
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    
    /* Center frame on the screen and take whole screen size*/
    view.setLocation(0, 0);
    view.setSize(screenSize);
  }
}
